import yfinance as yf
import numpy as np
import pandas as pd
data = yf.download("GOOG", start="2023-04-17")["Close"]
[*********************100%***********************] 1 of 1 completed
data.head(10)
Date 2023-04-17 106.419998 2023-04-18 105.120003 2023-04-19 105.019997 2023-04-20 105.900002 2023-04-21 105.910004 2023-04-24 106.779999 2023-04-25 104.610001 2023-04-26 104.449997 2023-04-27 108.370003 2023-04-28 108.220001 Name: Close, dtype: float64
data.tail(10)
Date 2023-05-15 116.959999 2023-05-16 120.089996 2023-05-17 121.480003 2023-05-18 123.519997 2023-05-19 123.250000 2023-05-22 125.870003 2023-05-23 123.290001 2023-05-24 121.639999 2023-05-25 124.349998 2023-05-26 125.430000 Name: Close, dtype: float64
log_returns = np.log(data/data.shift(1))
log_returns.dropna(inplace=True)
log_returns.head(10)
Date 2023-04-18 -0.012291 2023-04-19 -0.000952 2023-04-20 0.008344 2023-04-21 0.000094 2023-04-24 0.008181 2023-04-25 -0.020531 2023-04-26 -0.001531 2023-04-27 0.036843 2023-04-28 -0.001385 2023-05-01 -0.004724 Name: Close, dtype: float64
Volatility = log_returns.std() * sqrt(252)
Volatility
0.26837635271837934
t = 29/252
# Instantiate BSMCallOption with the required data
S0 = data.tail(1) # initial stock/index level
K = 130 # strike price
T = (t) # maturity (in year fractions)
r = 0.0511129 # risk-free short rate
sigma = (Volatility) # volatility factor in diffusion term
from math import log, sqrt, exp
from scipy.stats import norm
class BSMCallOption:
def __init__(self, S0, K, T, r, sigma):
self.S0 = float(S0)
self.K = K
self.T = T
self.r = r
self.sigma = sigma
def value(self):
d1 = (log(self.S0 / self.K) + (self.r + 0.5 * self.sigma ** 2) * self.T) / (self.sigma * sqrt(self.T))
d2 = d1 - self.sigma * sqrt(self.T)
value = self.S0 * norm.cdf(d1) - self.K * exp(-self.r * self.T) * norm.cdf(d2)
return value
def vega(self):
d1 = (log(self.S0 / self.K) + (self.r + 0.5 * self.sigma ** 2) * self.T) / (self.sigma * sqrt(self.T))
vega = self.S0 * norm.pdf(d1) * sqrt(self.T)
return vega
def imp_vol(self, C0, sigma_est=0.2, it=100):
option = BSMCallOption(self.S0, self.K, self.T, self.r, sigma_est)
for i in range(it):
option.sigma -= (option.value() - C0) / option.vega()
return option.sigma
option = BSMCallOption(S0, K, T, r, sigma)
# Calculate the option value
value = option.value()
print("Option Value:", value)
# Calculate the vega
vega = option.vega()
print("Vega:", vega)
# Estimate implied volatility
C0 = value # observed option price
implied_volatility = option.imp_vol(C0)
print("Implied Volatility:", implied_volatility)
Option Value: 2.9664470762478103 Vega: 16.308930963559423 Implied Volatility: 0.26837635271837906
maturities = np.linspace(0.05, 2.0, 20)
strikes = np.linspace(80, 120, 20)
K, T = np.meshgrid(strikes, maturities)
C = np.zeros_like(K)
V = np.zeros_like(C)
for t in enumerate(maturities):
for k in enumerate(strikes):
option.T = t[1]
option.K = k[1]
C[t[0], k[0]] = option.value()
V[t[0], k[0]] = option.vega()
import plotly.graph_objects as go
# Create a 3D surface plot
fig = go.Figure(data=[go.Surface(x=T, y=K, z=C)])
# Set axis labels and title
fig.update_layout(title='Option', autosize=True,
width=900, height=900,
margin=dict(l=65, r=50, b=65, t=90))
fig.show()